﻿$import( "SmitearWebGL.Objects.Primitive.Plane" );

SmitearWebGL.Objects.Primitive.Cube = SmitearWebGL.Objects.Mesh.extend(
{
	/* * * * * * * * constructor * * * * * * * */

	init : function()
	{
		this._super();
		this._registClass( "SmitearWebGL.Objects.Primitive.Cube" );
	}
	,
	_build : function( width, depth, height, segmentsS, segmentsT, segmentsH )
	{
		this.segments = new SmitearWebGL.Core.Geometry.Vertex( segmentsS, segmentsT, segmentsH );
		this.k = 0;

		var width2  = width  / 2;
		var height2 = height / 2;
		var depth2  = depth  / 2;

		var vertices = [];
		var vIndices = [];
		var tIndices = [];
		var uvs = [];

		this.buildPlane( "x", "y", width, height, depth2, ! SmitearWebGL.Objects.Primitive.Cube.Faces.FRONT, vIndices, vertices, tIndices, uvs );
		this.buildPlane( "x", "y", width, height, - depth2, SmitearWebGL.Objects.Primitive.Cube.Faces.BACK, vIndices, vertices, tIndices, uvs );
		this.buildPlane( "z", "y", depth, height, width2, SmitearWebGL.Objects.Primitive.Cube.Faces.RIGHT, vIndices, vertices, tIndices, uvs );
		this.buildPlane( "z", "y", depth, height, - width2, ! SmitearWebGL.Objects.Primitive.Cube.Faces.LEFT, vIndices, vertices, tIndices, uvs );
		this.buildPlane( "x", "z", width, depth, height2, SmitearWebGL.Objects.Primitive.Cube.Faces.TOP, vIndices, vertices, tIndices, uvs );
		this.buildPlane( "x", "z", width, depth, - height2, ! SmitearWebGL.Objects.Primitive.Cube.Faces.BOTTOM, vIndices, vertices, tIndices, uvs );

		this._adjacencyInfo = SmitearWebGL.Core.Geometry.Geometry.buildAdjacency( vIndices, vertices, tIndices, uvs );
		var dataObj = SmitearWebGL.Core.Geometry.Geometry.generateRawDatas( this._adjacencyInfo );
		
		this._boundingBox = SmitearWebGL.Core.Geometry.Geometry.computeBoundingBoxByVertices( this._adjacencyInfo.vertices );
		
		var vertDescs = [
			new SmitearWebGL.Resources.VertexElementDescription( this.context.gl, 3, 36, 0, SmitearWebGL.Resources.Buffer.DataType.FLOAT, SmitearWebGL.Resources.Buffer.AttribLocation.POSITION ),
			new SmitearWebGL.Resources.VertexElementDescription( this.context.gl, 3, 36, 12, SmitearWebGL.Resources.Buffer.DataType.FLOAT, SmitearWebGL.Resources.Buffer.AttribLocation.NORMAL ),
			new SmitearWebGL.Resources.VertexElementDescription( this.context.gl, 3, 36, 24, SmitearWebGL.Resources.Buffer.DataType.FLOAT, SmitearWebGL.Resources.Buffer.AttribLocation.TEXCOORD )
		]
		
		var idxDescs = [
			new SmitearWebGL.Resources.IndexElementDescription( this.context.gl, dataObj.rawIndices.length, 0, SmitearWebGL.Resources.Buffer.DataType.UNSIGNED_SHORT, SmitearWebGL.Resources.IndexBuffer.DrawType.TRIANGLES )
		]
		
		var vertexBufferData = dataObj.rawDatas;
		var indexBufferData = dataObj.rawIndices;
		
		this.createVertexBuffer( vertexBufferData, vertDescs );
		this.createIndexBuffer( indexBufferData, idxDescs );
	}
	,
	buildPlane : function( u, v, width, height, depth, reverse, vIndices, vertices, tIndices, uvs )
	{
		var w;
		if( ( u == "x" && v == "y" ) || ( u == "y" && v == "x" ) ) w = "z";
		else if( ( u == "x" && v == "z" ) || ( u == "z" && v == "x" ) ) w = "y";
		else if( ( u == "z" && v == "y" ) || ( u == "y" && v == "z" ) ) w = "x";

		// Mirror
		var rev = reverse ? - 1 : 1;

		var gridU = this.segments[ u ];
		var gridV = this.segments[ v ];
		var gridU1 = gridU + 1;
		var gridV1 = gridV + 1;
		var textureU = width / 2;
		var textureV = height / 2;
		var incU  = width / gridU;
		var incV  = height / gridV;
		var offset = vertices.length;

		// Vertices
		for( var iu = 0; iu < gridU1; iu ++ )
		{
			for( var iv = 0; iv < gridV1; iv ++ )
			{
				var vertex = new SmitearWebGL.Core.Geometry.Vertex();

				vertex[ u ] = ( iu * incU - textureU ) * rev;
				vertex[ v ] = iv * incV - textureV;
				vertex[ w ] = depth;

				vertices.push( vertex );
			}
		}

		// Faces
		var uvAUV;
		var uvCUV;
		var uvBUV;

		for(  iu = 0; iu < gridU; iu ++ )
		{
			for(  iv = 0; iv < gridV; iv ++ )
			{
				// Triangle A
				vIndices.push( iu     * gridV1 + iv + offset );
				vIndices.push( ( iu + 1 ) * gridV1 + iv + offset );
				vIndices.push( iu     * gridV1 + ( iv + 1 ) + offset );

				uvs.push( new SmitearWebGL.Core.Geometry.Uvt( iu     / gridU, iv     / gridV, 1.0 ) );
				uvs.push( new SmitearWebGL.Core.Geometry.Uvt( ( iu + 1 ) / gridU, iv     / gridV, 1.0 ) );
				uvs.push( new SmitearWebGL.Core.Geometry.Uvt( iu     / gridU, ( iv + 1 ) / gridV, 1.0 ) );

				tIndices.push( this.k ++ );
				tIndices.push( this.k ++ );
				tIndices.push( this.k ++ );

				// Triangle B
				vIndices.push( ( iu + 1 ) * gridV1 + iv + offset );
				vIndices.push( ( iu + 1 ) * gridV1 + ( iv + 1 ) + offset );
				vIndices.push( iu     * gridV1 + ( iv + 1 ) + offset );

				uvs.push( new SmitearWebGL.Core.Geometry.Uvt( ( iu + 1 ) / gridU, iv     / gridV, 1.0 ) );
				uvs.push( new SmitearWebGL.Core.Geometry.Uvt( ( iu + 1 ) / gridU, ( iv + 1 ) / gridV, 1.0 ) );
				uvs.push( new SmitearWebGL.Core.Geometry.Uvt( iu     / gridU, ( iv + 1 ) / gridV, 1.0 ) );

				tIndices.push( this.k ++ );
				tIndices.push( this.k ++ );
				tIndices.push( this.k ++ );
			}
		}
	}
	,
	_createResource : function( params )
	{
		this._super();
		
		if ( ! params )
		{
			params = {};
			params.width = 2.0;
			params.depth = 2.0;
			params.height = 2.0;
			params.segmentsW = 1.0;
			params.segmentsT = 1.0;
			params.segmentsH = 1.0;
		}
		
		this._build( params.width, params.depth, params.height, params.segmentsS, params.segmentsT, params.segmentsH );
	}
}
);

SmitearWebGL.Objects.Primitive.Cube.Faces =
{
	NONE    : 0x00,
	FRONT   : 0x01,
	BACK    : 0x02,
	RIGHT   : 0x04,
	LEFT    : 0x08,
	TOP     : 0x10,
	BOTTOM  : 0x20
}